import { Role } from './../entitys/Role';
import { User } from './../entitys/User';
import { getRepository, In, FindConditions, Like, getConnection } from 'typeorm';
import { Menu } from './../entitys/Menu';
import { Inject, Service } from "typedi";
import UserService from './UserService';

@Service()
export default class MenuService {
    @Inject()
    private userService: UserService
    async addMenu(menu: Menu) {
        if (menu.parentId == undefined) {
            menu.parentId = 0
        }
        if (menu.type == 1 && menu.isShowMenu == undefined) {
            menu.isShowMenu = 1//默认菜单显示
        }
        menu.createTime = new Date()
        menu.updateTime = new Date()
        menu.dataStatus = 1
        const menuRepository = getRepository(Menu)
        const connection = getConnection()
        await menuRepository.save(menu)
        await connection.queryResultCache.remove(["getMenuTree"])
        return
    }
    async updateMenu(menu: any) {
        const menuRepository = getRepository(Menu)
        let menuEntity: any = await menuRepository.findOne(menu.id)
        if (!menuEntity) {
            return false
        }
        for (let key of Object.keys(menuEntity)) {
            let value = menu[key]
            if (key == "id") {
                continue
            }
            if (value || value === 0) {
                menuEntity[key] = value
            }
        }
        const connection = getConnection()
        await menuRepository.save(menuEntity)
        await connection.queryResultCache.remove(["getMenuTree"])
        return true
    }
    async delMenu(id: number) {
        const repository = getRepository(Menu)
        const dataStatus = 1
        const menus = await repository.find({
            where: [
                {
                    id: id,
                    dataStatus
                },
                {
                    parentId: id,
                    dataStatus
                }
            ],
        })
        if (!menus || menus.length === 0) {
            throw new Error("通过id=" + id + "未找到对应菜单")
        }
        menus.forEach(menu => {
            menu.dataStatus = -1
        })
        repository.save(menus)
    }
    async getUserMenu(user: User) {
        user = await this.userService.getUserById(user.id)
        let roleIdArr = user.roles.map(role => role.id)
        let roleRepository = getRepository(Role)
        let roles = await roleRepository.createQueryBuilder("role").
            leftJoinAndSelect("role.menus", "menu", "menu.dataStatus = 1 and menu.type = 1 and menu.isShowMenu = 1").andWhereInIds(roleIdArr).
            getMany()
        let menus: Menu[] = []
        roles.forEach(role => {
            menus.push(...role.menus)
        })
        this.distinctArr(menus)
        let menuRootTree = this.getMenu(menus, 0)
        this.getChildren(menuRootTree, menus)
        return menuRootTree
    }
    async getUserRouters(user: User) {
        user = await this.userService.getUserById(user.id)
        let roleIdArr = user.roles.map(role => role.id)
        let roleRepository = getRepository(Role)
        let roles = await roleRepository.createQueryBuilder("role").
            leftJoinAndSelect("role.menus", "menu", "menu.dataStatus = 1 and menu.type = 1 ").andWhereInIds(roleIdArr).
            getMany()
        let menus: Menu[] = []
        roles.forEach(role => {
            menus.push(...role.menus)
        })
        menus.forEach((m: any) => {
            m.meta = {}
            m.meta.hidden = m.isShowMenu !== 1
            delete m.isShowMenu
            m.meta.icon = m.icon
            delete m.icon
            m.meta.title = m.name
        })
        this.distinctArr(menus)
        let menuRootTree = this.getMenu(menus, 0)
        this.getChildren(menuRootTree, menus)
        return menuRootTree
    }
    async getMenuTree(menuName: string) {
        let where: FindConditions<Menu> = { dataStatus: 1 }
        if (menuName) {
            where.name = Like("%" + menuName + "%")
        }
        const menuRepository = getRepository(Menu)
        let menus = await menuRepository.find({
            where,
            order: {
                sort: 'ASC',
                createTime: 'ASC'
            },
            // cache: {
            //     id: 'getMenuTree',
            //     milliseconds: 300000
            // }
        })
        if (menus && menus.length > 0) {
            let menuTree = this.getMenu(menus, 0)
            if (menuTree.length > 0) {
                this.getChildren(menuTree, menus)
            } else {
                return menus
            }
            if (menus.length > 0) {
                menuTree.push(...menus)
            }
            return menuTree
        }
        return []
    }
    private getMenu(menus: Menu[], parentId: number) {
        let rootMenu = []
        for (let i = 0; i < menus.length; i++) {
            let menu = menus[i]
            if (menu.parentId == parentId) {
                rootMenu.push(menu)
                menus.splice(i, 1)
                i--
            }
        }
        rootMenu.sort((menu1, menu2) => {
            return menu1.sort - menu2.sort
        })
        return rootMenu
    }
    private getChildren(rootTree: Menu[], menus: Menu[]) {
        rootTree.forEach((menu: any) => {
            let children = this.getMenu(menus, menu.id)
            if (children.length > 0) {
                menu.children = children
                this.getChildren(menu.children, menus)
            }
        })
    }
    private distinctArr(menus: Menu[]) {
        menus.sort((menu1, menu2) => {
            return menu2.sort - menu1.sort
        })
        for (let i = 1; i < menus.length; i++) {
            let firstIndex = menus.findIndex(menu => menu.id == menus[i].id)
            if (firstIndex != i) {
                menus.splice(i, 1)
                i--
            }
        }
    }
    /**
 * 获取菜单
 * @param menuIds 
 */
    public async getMenusByIds(menuIds: string[]) {
        let menus
        if (menuIds) {
            const menuRepository = getRepository(Menu)
            let menuIdArr = menuIds.map(id => Number(id))
            menus = await menuRepository.find({
                id: In(menuIdArr)
            })
        }
        return menus
    }
    public async getMenuById(id: number) {
        const menuRepository = getRepository(Menu)
        let menu = await menuRepository.findOne(id)
        return menu
    }

}